package com.yupi.springbootinit.service;

import com.yupi.springbootinit.model.entity.DeviceInfo;
import com.yupi.springbootinit.model.vo.DeviceStatusVO;
import com.yupi.springbootinit.repository.InfluxRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;


/**
 * @Author:WwW
 * @Description
 * @Date: 2025/9/19  09:02
 */
@Service
@RequiredArgsConstructor
public class StatisticsService {

    private final InfluxRepository influxRepository;
    private final DeviceInfoService deviceInfoService;

    /**
     * 计算设备可用性比率
     * @param deviceId 设备ID
     * @param range 时间范围，相对时间格式，例如 "-24h"
     * @param includeBusy 是否将忙碌状态(3)计为运行状态
     * @return 设备在指定时间范围内的可用性比率
     */
    public double calcAvailability(Integer deviceId, String range, boolean includeBusy) {
        DeviceInfo d = deviceInfoService.getById(deviceId);
        if (d == null) return 0.0;

        // 支持 CSV measurements
        List<String> ms = d.getInfluxMeasurementList();
        if (ms == null || ms.isEmpty()) {
            ms = List.of("MODBUS".equalsIgnoreCase(d.getProtocolType()) ? "modbus_data" : "device_data_mqtt");
        }
        ms = ms.stream().map(s -> s.replace('-', '_')).toList();

        Double ratio = influxRepository.queryAvailabilityWeightedRelMulti(
                ms, d.getInfluxTagName(), range, includeBusy
        );
        return ratio != null ? ratio : 0.0;
    }

    /**
     * 计算设备状态进度
     * @param status 设备状态VO对象
     * @return 进度百分比
     */
    public double calcProgress(DeviceStatusVO status) {
        Double p1 = calcBy(status.getTotalAccount(), status.getRemainingAccount());
        Double p2 = calcBy(status.getTotalHeight(), status.getRemainingHeight());
        Double p3 = calcBy(status.getEstimatedTime(), status.getRemainingTime());

        return Stream.of(p1, p2, p3)
                .filter(Objects::nonNull)
                .map(v -> Math.max(0.0, Math.min(100.0, v)))
                .max(Double::compare)
                .orElse(0.0);
    }

    /**
     * 根据总量和剩余量计算进度百分比
     * @param total 总量
     * @param remain 剩余量
     * @return 进度百分比
     */
    private Double calcBy(Integer total, Integer remain) {
        if (total == null || remain == null || total <= 0) return null;
        return (1 - remain * 1.0 / total) * 100;
    }

    /**
     * 根据总量和剩余量计算进度百分比（双精度浮点数版本）
     * @param total 总量
     * @param remain 剩余量
     * @return 进度百分比
     */
    private Double calcBy(Double total, Double remain) {
        if (total == null || remain == null || total <= 0) return null;
        return (1 - remain / total) * 100;
    }
}
